# -*- coding: utf-8 -*-

# Módulos
import base64
import gzip
import StringIO
from xml.dom import minidom

def load_map(source):
    """ Crea un diccionario con los datos de un mapa tmx"""
    map = {}
    map['properties'] = {}
    map['tilesets'] = []
    map['layers'] = []
    map['events'] = []

    xmlMap = minidom.parse(source)
    mainNode = xmlMap.childNodes[0]

    # Name
    name = extract_name(source)
    name = quit_extension(name)
    map['name'] = name

    #size
    w = int(mainNode.attributes.get("width").value)
    h = int(mainNode.attributes.get("height").value)
    map['size'] = (w, h)

    # Tiles Size
    w = int(mainNode.attributes.get("tilewidth").value)
    h = int(mainNode.attributes.get("tileheight").value)
    map['tile_size'] = (w, h)

    for i in range(len(mainNode.childNodes)):
        if mainNode.childNodes[i].nodeType == 1:
            # Propiedades del mapa
            if mainNode.childNodes[i].nodeName == "properties":
                for j in range(len(mainNode.childNodes[i].childNodes)):
                    if mainNode.childNodes[i].childNodes[j].nodeType == 1:
                        name = mainNode.childNodes[i].childNodes[j].attributes.get("name").value
                        value = mainNode.childNodes[i].childNodes[j].attributes.get("value").value
                        value = convert_string(value)
                        map['properties'][name] = value
            # Tilesets
            if mainNode.childNodes[i].nodeName == "tileset":
                tileset = {}
                # Número del primer tile
                tileset['firstgid'] = int(mainNode.childNodes[i].attributes.get("firstgid").value)
                # Tamaño de los tiles
                w = int(mainNode.childNodes[i].attributes.get("tilewidth").value)
                h = int(mainNode.childNodes[i].attributes.get("tileheight").value)
                tileset['tile_size'] = (w, h)
                # Imagen del tileset
                image = mainNode.childNodes[i].getElementsByTagName("image")[0]
                source = image.attributes.get("source").value
                tileset['image'] = extract_name(source)
                # Tamaño del tileset
                w = int(image.attributes.get("width").value)
                h = int(image.attributes.get("height").value)
                tileset['size'] = (w, h)
                try:
                    color = image.attributes.get("trans").value
                    tileset['color'] = color
                except:
                    tileset['color'] = None
                map['tilesets'].append(tileset)
            # Layers
            if mainNode.childNodes[i].nodeName == "layer":
                node = mainNode.childNodes[i]
                layer = {}
                layer['name'] = node.attributes.get("name").value
                layer['properties'] = {}
                for j in range(len(node.childNodes)):
                    if node.childNodes[j].nodeType == 1:
                        if node.childNodes[j].nodeName == "properties":
                            for k in range(len(mainNode.childNodes[i].childNodes[j].childNodes)):
                                if mainNode.childNodes[i].childNodes[j].childNodes[k].nodeType == 1:
                                    name = mainNode.childNodes[i].childNodes[j].childNodes[k].attributes.get("name").value
                                    value = mainNode.childNodes[i].childNodes[j].childNodes[k].attributes.get("value").value
                                    value = convert_string(value)
                                    layer['properties'][name] = value
                        if mainNode.childNodes[i].childNodes[j].nodeName == "data":
                            data = mainNode.childNodes[i].childNodes[j].childNodes[0].data.replace("\n", "").replace(" ", "")
                            data = decode(data) # Decodifica la lista
                            data = convert(data, map['size'][0]) # Convierta en array bidimensional
                            layer['data'] = data
                        map['layers'].append(layer)

    return map

# Decodifica una cadena en base64 y luego la descomprime.
def decode(cadena):
    # Decodificar.
    cadena = base64.decodestring(cadena)

    # Descomprimir.
    copmressed_stream = StringIO.StringIO(cadena)
    gzipper = gzip.GzipFile(fileobj=copmressed_stream)
    cadena = gzipper.read()

    # Convertir.
    salida = []
    for idx in xrange(0, len(cadena), 4):
        val = ord(str(cadena[idx])) | (ord(str(cadena[idx + 1])) << 8) | \
        (ord(str(cadena[idx + 2])) << 16) | (ord(str(cadena[idx + 3])) << 24)
        salida.append(val)

    return salida

# Convierta una array unidimensional en una bidimensional.
def convert(lista, col):
    nueva = []
    for i in range(0, len(lista), col):
        nueva.append(lista[i:i+col])
    return nueva

# Extra el name de un archivo de una ruta.
def extract_name(ruta):
    a = -1
    for i in range(len(ruta)):
        if ruta[i] == "/" or ruta[i] == "\\":
            a = i
    if a == -1:
        return ruta
    return ruta[a+1:]

# Quita la extensión a un archivo.
def quit_extension(archivo):
    for i in range(len(archivo)):
        if archivo[i] == ".":
            a = i
    return archivo[:a]

# Convierte una cadena a un int o un float si es posible
def convert_string(string):
    values = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', "."]
    for i in string:
        if not i in values:
            return string
    for i in string:
        if i == ".":
            return float(string)
    return int(string)

def main():
    return 0

if __name__ == '__main__':
    main()
